#include "adalog/buffer/Buffer.h"

namespace adalog
{
    Buffer::Buffer()
        : write_pos_(0)
        , read_pos_(0)
        , buffer_(4 * 1024, 0)
        , threshold_(4 * 1024 * 1024 * 8)
        , linear_growth_(4 * 1024 * 8)
    {
    }

    void Buffer::Push(const char* data, size_t len)
    {
        // 确保容量足够，在容量不足时会扩容
        size_t write_pos = write_pos_.fetch_add(len);
        ToBeEnouth(len);
        std::copy(data, data + len, &buffer_[write_pos]);
    }

    char* Buffer::ReadBegin(size_t len)
    {
        assert(len <= ReadableSize());
        return &buffer_[read_pos_];
    }

    bool Buffer::IsEmpty() const
    {
        return read_pos_ == write_pos_;
    }

    void Buffer::Swap(Buffer& buf)
    {
        buffer_.swap(buf.buffer_);
        size_t temp = write_pos_.exchange(temp);
        buf.write_pos_.store(temp);
        std::swap(read_pos_, buf.read_pos_);
    }

    size_t Buffer::WritableSize() const 
    {
        // 写空间剩余容量
        return buffer_.capacity() - write_pos_;
    }

    size_t Buffer::ReadableSize() const
    {
        return write_pos_ - read_pos_;
    }

    const char* Buffer::Begin() const
    {
        return &buffer_[read_pos_];
    }

    void Buffer::MoveWritePos(size_t len)
    {
        assert(len <= WritableSize());
        write_pos_ += len;
    }

    void Buffer::MoveReadPos(size_t len)
    {
        assert(len <= ReadableSize());
        read_pos_ += len;
    }

    void Buffer::Reset()
    {
        write_pos_.store(0);
        read_pos_ = 0;
    }

    void Buffer::ToBeEnouth(size_t len)
    {
        int buffersize = buffer_.capacity();
        if (len > WritableSize())
        {
            if (buffersize < threshold_)
            {
                buffer_.resize(2 * buffersize);
            }
            else
            {
                buffer_.resize(linear_growth_ + buffersize);
            }
        }
    }
} // namespace adalog